package com.leon.config;

import com.alibaba.druid.pool.DruidDataSource;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DbConnectionManager {

    private DbConnectionManager() {}

    private static DbConnectionManager manager;
    private static DruidDataSource dataSource;

    // 使用锁保证并发, 避免重构连接池和获取连接的并发问题
    private static Lock lock = new ReentrantLock();

    /**
     * 用单例模式保证初始化过程只能运行一次
     * @param entity
     */
    public synchronized static void initManager(DBEntity entity) {
        if (manager == null) {
            manager = new DbConnectionManager();
            manager.initPool(entity);
        }
    }


    public static void initPool(DBEntity entity) {
        System.out.println("----------------- init datasource -----------------");
        doInitDataSource(entity);
    }

    /** 重新构建连接池
     *
     * @param entity
     */
    public static void refreshPool(DBEntity entity) {
        System.out.println("----------------- rebuild datasource -----------------");
        lock.lock();
        try {
            // 释放原来的连接
            dataSource.close();
            // 释放完成后,重新初始化一个新的数据库连接池
            if (dataSource.isClosed()) {
                doInitDataSource(entity);
            }
        } finally {
            lock.unlock();
        }
    }

    public static Connection getConnection() throws SQLException {
        Connection connection;
        lock.lock();
        try {
            connection = dataSource.getConnection();
        } finally {
            lock.unlock();
        }

        return connection;
    }

    private static void doInitDataSource(DBEntity entity) {
        dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUsername(entity.getUserName());
        dataSource.setPassword(entity.getPassword());
        dataSource.setUrl(entity.getUrl());
        dataSource.setInitialSize(5);
        dataSource.setMinIdle(1);
        dataSource.setMaxActive(10);

        dataSource.setPoolPreparedStatements(false);
    }

}
